/*
 * @Author: 尚博信_王强 wangqiang03@sunboxsoft.com
 * @Date: 2022-07-15 16:18:49
 * @LastEditors: 尚博信_王强 wangqiang03@sunboxsoft.com
 * @LastEditTime: 2023-07-21 12:24:47
 * @FilePath: /CDP-ZHACAPP/JMZHAC/src/components/CustomTabBar.js
 * @Description: 自定义ScrollableTabBar底部滑动条
 */

import React from 'react'
import {getSize} from '../utils/StyleSheet375'
// const { ViewPropTypes } = ReactNative = require('deprecated-react-native-prop-types');
import {ViewPropTypes} from 'deprecated-react-native-prop-types'
const PropTypes = require('prop-types');
const createReactClass = require('create-react-class');
import  {
  View,
  Animated,
  StyleSheet,
  ScrollView,
  Text,
  Platform,
  Dimensions,
  TouchableOpacity
} from 'react-native'

const WINDOW_WIDTH = Dimensions.get('window').width;

class ScrollableTabBar extends React.Component {
    static propTypes = {
        goToPage: PropTypes.func,
        activeTab: PropTypes.number,
        tabs: PropTypes.array,
        backgroundColor: PropTypes.string,
        activeTextColor: PropTypes.string,
        inactiveTextColor: PropTypes.string,
        scrollOffset: PropTypes.number,
        style: ViewPropTypes.style,
        tabStyle: ViewPropTypes.style,
        tabsContainerStyle: ViewPropTypes.style,
        textStyle: Text.propTypes.style,
        renderTab: PropTypes.func,
        underlineStyle: ViewPropTypes.style,
        onScroll: PropTypes.func,
    }

    static defaultProps = {
        scrollOffset: 52,
        activeTextColor: 'navy',
        inactiveTextColor: 'black',
        backgroundColor: null,
        style: {},
        tabStyle: {},
        tabsContainerStyle: {},
        underlineStyle: {},
    }

    constructor(props) {
        super(props);
        this._tabsMeasurements = [];
        this.state = {
            _leftTabUnderline: new Animated.Value(0),
            _widthTabUnderline: new Animated.Value(0),
            _containerWidth: null,
        }
    }

    componentDidMount() {
        this.props.scrollValue.addListener(this.updateView);
      }
    
      updateView(offset) {
        const position = Math.floor(offset.value);
        const pageOffset = offset.value % 1;
        const tabCount = this.props.tabs.length;
        const lastTabPosition = tabCount - 1;
    
        if (tabCount === 0 || offset.value < 0 || offset.value > lastTabPosition) {
          return;
        }
    
        if (this.necessarilyMeasurementsCompleted(position, position === lastTabPosition)) {
          this.updateTabPanel(position, pageOffset);
          this.updateTabUnderline(position, pageOffset, tabCount);
        }
      }
    
      necessarilyMeasurementsCompleted(position, isLastTab) {
        return this._tabsMeasurements[position] &&
          (isLastTab || this._tabsMeasurements[position + 1]) &&
          this._tabContainerMeasurements &&
          this._containerMeasurements;
      }
    
      updateTabPanel(position, pageOffset) {
        const containerWidth = this._containerMeasurements.width;
        const tabWidth = this._tabsMeasurements[position].width;
        const nextTabMeasurements = this._tabsMeasurements[position + 1];
        const nextTabWidth = nextTabMeasurements && nextTabMeasurements.width || 0;
        const tabOffset = this._tabsMeasurements[position].left;
        const absolutePageOffset = pageOffset * tabWidth;
        let newScrollX = tabOffset + absolutePageOffset;
    
        // center tab and smooth tab change (for when tabWidth changes a lot between two tabs)
        newScrollX -= (containerWidth - (1 - pageOffset) * tabWidth - pageOffset * nextTabWidth) / 2;
        newScrollX = newScrollX >= 0 ? newScrollX : 0;
    
        if (Platform.OS === 'android') {
          this._scrollView.scrollTo({x: newScrollX, y: 0, animated: false, });
        } else {
          const rightBoundScroll = this._tabContainerMeasurements.width - (this._containerMeasurements.width);
          newScrollX = newScrollX > rightBoundScroll ? rightBoundScroll : newScrollX;
          this._scrollView.scrollTo({x: newScrollX, y: 0, animated: false, });
        }
    
      }
    
      updateTabUnderline(position, pageOffset, tabCount) {
        const lineLeft = this._tabsMeasurements[position].left;
        const lineRight = this._tabsMeasurements[position].right;
    
        if (position < tabCount - 1) {
          const nextTabLeft = this._tabsMeasurements[position + 1].left;
          const nextTabRight = this._tabsMeasurements[position + 1].right;
    
          const newLineLeft = (pageOffset * nextTabLeft + (1 - pageOffset) * lineLeft);
          const newLineRight = (pageOffset * nextTabRight + (1 - pageOffset) * lineRight);
    
          this.state._leftTabUnderline.setValue(newLineLeft+getSize(27));
          this.state._widthTabUnderline.setValue(newLineRight - newLineLeft-getSize(54));
        } else {
          this.state._leftTabUnderline.setValue(lineLeft + getSize(27));
          this.state._widthTabUnderline.setValue(lineRight - lineLeft - getSize(54));
        }
      }
    
      renderTab(name, page, isTabActive, onPressHandler, onLayoutHandler) {
        const { activeTextColor, inactiveTextColor, textStyle, } = this.props;
        const textColor = isTabActive ? activeTextColor : inactiveTextColor;
        const fontWeight = isTabActive ? 'normal' : 'normal';
    
        return <TouchableOpacity
            activeOpacity={1}
          key={`${name}_${page}`}
          accessible={true}
          accessibilityLabel={name}
          accessibilityTraits='button'
          onPress={() => onPressHandler(page)}
          onLayout={onLayoutHandler}
        >
          <View style={[styles.tab, this.props.tabStyle, ]}>
            <Text style={[{color: textColor, fontWeight, }, textStyle,{fontSize:isTabActive?14:14} ]}>
              {name}
            </Text>
          </View>
        </TouchableOpacity>;
      },
    
      measureTab(page, event) {
        const { x, width, height, } = event.nativeEvent.layout;
        this._tabsMeasurements[page] = {left: x, right: x + width, width, height, };
        this.updateView({value: this.props.scrollValue.__getValue(), });
      }
    
      render() {
        const tabUnderlineStyle = {
          position: 'absolute',
          height: 4,
          backgroundColor: 'navy',
          bottom: 0,
        };
    
        const dynamicTabUnderline = {
          left: this.state._leftTabUnderline,
          width: this.state._widthTabUnderline,
        };
    
        return <View
          style={[styles.container, {backgroundColor: this.props.backgroundColor, }, this.props.style, ]}
          onLayout={this.onContainerLayout}
        >
          <ScrollView
            ref={(scrollView) => { this._scrollView = scrollView; }}
            horizontal={true}
            showsHorizontalScrollIndicator={false}
            showsVerticalScrollIndicator={false}
            directionalLockEnabled={true}
            bounces={false}
            scrollsToTop={false}
          >
            <View
              style={[styles.tabs, {width: this.state._containerWidth, }, this.props.tabsContainerStyle, ]}
              ref={'tabContainer'}
              onLayout={this.onTabContainerLayout}
            >
              {this.props.tabs.map((name, page) => {
                const isTabActive = this.props.activeTab === page;
                const renderTab = this.props.renderTab || this.renderTab;
                return renderTab(name, page, isTabActive, this.props.goToPage, this.measureTab.bind(this, page));
              })}
              <Animated.View style={[tabUnderlineStyle, dynamicTabUnderline, this.props.underlineStyle, ]} />
            </View>
          </ScrollView>
        </View>;
      }
    
      componentDidUpdate(prevProps) {
        // If the tabs change, force the width of the tabs container to be recalculated
        if (JSON.stringify(prevProps.tabs) !== JSON.stringify(this.props.tabs) && this.state._containerWidth) {
          this.setState({ _containerWidth: null, });
        }
      }
    
      onTabContainerLayout(e) {
        this._tabContainerMeasurements = e.nativeEvent.layout;
        let width = this._tabContainerMeasurements.width;
        if (width < WINDOW_WIDTH) {
          width = WINDOW_WIDTH;
        }
        this.setState({ _containerWidth: width, });
        this.updateView({value: this.props.scrollValue.__getValue(), });
      }
    
      onContainerLayout(e) {
        this._containerMeasurements = e.nativeEvent.layout;
        this.updateView({value: this.props.scrollValue.__getValue(), });
      }
}



module.exports = ScrollableTabBar;

const styles = StyleSheet.create({
  tab: {
    height: 35,
    alignItems: 'center',
    justifyContent: 'center',
    paddingLeft: 25,
    paddingRight: 25,
  },
  container: {
    height: 35,
    borderWidth: 0,
    borderTopWidth: 0,
    borderLeftWidth: 0,
    borderRightWidth: 0,
    borderColor: '#ccc',
  },
  tabs: {
    flexDirection: 'row',
    justifyContent: 'space-around',
  },
});
